All files / core/stats StatsReporter.ts

85.71% Statements 24/28
66.67% Branches 4/6
80% Functions 4/5
84.62% Lines 22/26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79                                12x 12x 12x             12x 12x     12x         12x   15x           15x 15x     15x   15x     12x       12x 10x 10x 10x   10x 8x           10x         10x         12x  
/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
import { contains, forEach } from '@firebase/util';
import { setTimeoutNonBlocking } from '../util/util';
import { StatsListener } from './StatsListener';
import { StatsCollection } from './StatsCollection';
import { ServerActions } from '../ServerActions';
 
// Assuming some apps may have a short amount of time on page, and a bulk of firebase operations probably
// happen on page load, we try to report our first set of stats pretty quickly, but we wait at least 10
// seconds to try to ensure the Firebase connection is established / settled.
const FIRST_STATS_MIN_TIME = 10 * 1000;
const FIRST_STATS_MAX_TIME = 30 * 1000;
 
// We'll continue to report stats on average every 5 minutes.
const REPORT_STATS_INTERVAL = 5 * 60 * 1000;
 
/**
 * @constructor
 */
export class StatsReporter {
  private statsListener_: StatsListener;
  private statsToReport_: { [k: string]: boolean } = {};
 
  /**
   * @param collection
   * @param server_
   */
  constructor(collection: StatsCollection, private server_: ServerActions) {
    this.statsListener_ = new StatsListener(collection);
 
    const timeout =
      FIRST_STATS_MIN_TIME +
      (FIRST_STATS_MAX_TIME - FIRST_STATS_MIN_TIME) * Math.random();
    setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(timeout));
  }
 
  includeStat(stat: string) {
    this.statsToReport_[stat] = true;
  }
 
  private reportStats_() {
    const stats = this.statsListener_.get();
    const reportedStats: typeof stats = {};
    let haveStatsToReport = false;
 
    forEach(stats, (stat: string, value: number) => {
      Iif (value > 0 && contains(this.statsToReport_, stat)) {
        reportedStats[stat] = value;
        haveStatsToReport = true;
      }
    });
 
    Iif (haveStatsToReport) {
      this.server_.reportStats(reportedStats);
    }
 
    // queue our next run.
    setTimeoutNonBlocking(
      this.reportStats_.bind(this),
      Math.floor(Math.random() * 2 * REPORT_STATS_INTERVAL)
    );
  }
}